﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ControlPanel
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    /// 


    public class EcoSphere
    {
        public EcoSphere(MainWindow mw)
        {
            this.mw = mw;
            psi = new ProcessStartInfo("EcoSphere.exe");
            psi.Arguments = "-cp";
            psi.CreateNoWindow = true;
            psi.UseShellExecute = false;
            psi.RedirectStandardError = true;
            psi.RedirectStandardInput = true;
            psi.RedirectStandardOutput = true;
        }

        public void Exit()
        {
            process.StandardInput.WriteLine("exit");
        }

        public void GetData()
        {
            Input("data");
        }

        public void ThreadFunction()
        {
            try
            {
                process = Process.Start(psi);
                process.OutputDataReceived += (s, _e) => mw.CoutReceived(_e.Data);
                process.ErrorDataReceived += (s, _e) => mw.CerrReceived(_e.Data);
                process.BeginErrorReadLine();
                process.BeginOutputReadLine();
                process.WaitForExit();

            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
        public void RunProgram()
        {
            Thread thread = new Thread(ThreadFunction);
            thread.Start();
        }

        public void Input(string s)
        {
            process.StandardInput.WriteLine(s);
        }

        public void Run()
        {
            Input("run");
        }

        public void Stop()
        {
            Input("stop");
        }

        public void Pause()
        {
            Input("pause");
        }

        public void Resume()
        {
            Input("resume");
        }

        public void Spawn(string species, uint count)
        {
            Input("spawn " + species + ' ' + count);
        }

        public void FlushMemory()
        {
            Input("flushMemory");
        }

        public void EnableImage()
        {
            Input("enableImage");
        }

        public void DisableImage()
        {
            Input("disableImage");
        }

        public void Plot(string s)
        {
            Input("plot " + s);
        }

        public long GetMemoryUsed()
        {
            return process.PrivateMemorySize64 / 1024;
        }
        private ProcessStartInfo psi;
        private Process process;
        private MainWindow mw;
    }


    public partial class MainWindow : Window
    {
        private EcoSphere ecosphere;
        public MainWindow()
        {
            InitializeComponent();
            ecosphere = new EcoSphere(this);
            ecosphere.RunProgram();
        }

        public void CoutReceived(String s)
        {
            this.Cout.Dispatcher.Invoke
            (
                new Action
                (
                    delegate
                    {
                        Cout.AppendText(s + '\n');
                        Cout.ScrollToEnd();
                        if(s == "Ecosystem deleted...")
                        {
                            Run.IsEnabled = true;
                            Spawn.IsEnabled = true;
                        }

                        if(s == "Ecosystem paused...")
                        {
                            Resume.IsEnabled = true;
                            Spawn.IsEnabled = true;
                            Plot.IsEnabled = true;
                        }
                    }
                )
            );
        }

        public void CerrReceived(String s)
        {
            //MessageBox.Show(s);
            string[] data = s.Split('|');
            //if(data.Length >= 17)
            {
                this.brightness.Dispatcher.Invoke(          
                    new Action(delegate { brightness.Text = data[0]; })
                );
                this.temperature.Dispatcher.Invoke(         
                    new Action(delegate { temperature.Text = data[1]; })
                );
                this.rainfall.Dispatcher.Invoke(            
                    new Action(delegate { rainfall.Text = data[2]; })
                );
                this.relativehumidity.Dispatcher.Invoke(    
                    new Action(delegate { relativehumidity.Text = data[3]; })
                );
                this.weather.Dispatcher.Invoke(             
                    new Action(delegate { weather.Text = data[4]; })
                );
                this.season.Dispatcher.Invoke(              
                    new Action(delegate { season.Text = data[5]; })
                );
                this.grass.Dispatcher.Invoke(               
                    new Action(delegate { grass.Text = data[6]; })
                );
                this.tree.Dispatcher.Invoke(                
                    new Action(delegate { tree.Text = data[7]; })
                );
                this.ant.Dispatcher.Invoke(                 
                    new Action(delegate { ant.Text = data[8]; })
                );
                this.cow.Dispatcher.Invoke(                 
                    new Action(delegate { cow.Text = data[9]; })
                );
                this.tiger.Dispatcher.Invoke(               
                    new Action(delegate { tiger.Text = data[10]; })
                );
                this.elephant.Dispatcher.Invoke(
                    new Action(delegate { elephant.Text = data[11]; })
                );
                this.giraffe.Dispatcher.Invoke(
                    new Action(delegate { giraffe.Text = data[12]; })
                );
                this.bird.Dispatcher.Invoke(
                    new Action(delegate { bird.Text = data[13]; })
                );
                this.eagle.Dispatcher.Invoke(
                    new Action(delegate { eagle.Text = data[14]; })
                );
                this.snake.Dispatcher.Invoke(
                    new Action(delegate { snake.Text = data[15]; })
                );
                this.frog.Dispatcher.Invoke(
                    new Action(delegate { frog.Text = data[16]; })
                );
                this.insect.Dispatcher.Invoke(
                    new Action(delegate { insect.Text = data[17]; })
                );
                this.lastticktime.Dispatcher.Invoke(
                    new Action(delegate { lastticktime.Text = data[18]; })
                );
            }
        }

        private void Run_Click(object sender, RoutedEventArgs e)
        {
            ecosphere.Run();
            Run.IsEnabled       = false;
            Stop.IsEnabled      = true;
            Pause.IsEnabled     = true;
            Resume.IsEnabled    = false;
            Spawn.IsEnabled     = false;
            Plot.IsEnabled      = false;

        }

        private void Stop_Click(object sender, RoutedEventArgs e)
        {
            ecosphere.Stop();
            Run.IsEnabled = false;
            Stop.IsEnabled = false;
            Pause.IsEnabled = false;
            Resume.IsEnabled = false;
            Spawn.IsEnabled = false;
            Plot.IsEnabled = false;
        }

        private void Pause_Click(object sender, RoutedEventArgs e)
        {
            ecosphere.Pause();
            Run.IsEnabled = false;
            Stop.IsEnabled = false;
            Pause.IsEnabled = false;
            Resume.IsEnabled = false;
            Spawn.IsEnabled = false;
            Plot.IsEnabled = false;
        }

        private void Resume_Click(object sender, RoutedEventArgs e)
        {
            ecosphere.Resume();
            Run.IsEnabled = false;
            Stop.IsEnabled = true;
            Pause.IsEnabled = true;
            Resume.IsEnabled = false;
            Spawn.IsEnabled = false;
            Plot.IsEnabled = false;
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            ecosphere.Exit();
            Application.Current.Shutdown();
        }

        private void Spawn_Click(object sender, RoutedEventArgs e)
        {
            if (spawncount.Text.Length == 0)
                return;
            ComboBoxItem cbi = (ComboBoxItem)species.SelectedItem;
            uint count = 0;
            bool flag = true;
            try
            {
                count = uint.Parse(spawncount.Text);
            }
            catch(Exception ex)
            {
                flag = false;
            }
            if (cbi != null && flag)
                ecosphere.Spawn(cbi.Content.ToString(), count);
        }

        private void species_SelectionChanged(object sender, RoutedEventArgs e)
        {
            spawncount.Clear();
        }

        private bool enableImage = false;
        private void ToogleImage_Click(object sender, RoutedEventArgs e)
        {
            if(enableImage)
            {
                ToogleImage.Content = "Image: Disabled";
                ecosphere.DisableImage();
            }
            else
            {
                ToogleImage.Content = "Image: Enabled";
                ecosphere.EnableImage();
            }
            enableImage = !enableImage;
        }

        private void Plot_Click(object sender, RoutedEventArgs e)
        {
            ComboBoxItem cbi = (ComboBoxItem)plotComboBox.SelectedItem;
            if (cbi != null)
                ecosphere.Plot(cbi.Content.ToString());

        }

        private void commandInputBox_KeyUp(object sender, KeyEventArgs e)
        {
            if(e.Key == Key.Enter)
            {
                if(commandInputBox.Text == "enable all buttons")
                {
                    Run.IsEnabled = true;
                    Stop.IsEnabled = true;
                    Pause.IsEnabled = true;
                    Resume.IsEnabled = true;
                    Spawn.IsEnabled = true;
                    Plot.IsEnabled = true;
                }
                else
                    ecosphere.Input(commandInputBox.Text);
                commandInputBox.Clear();
            }
        }

        private void developerTools_Click(object sender, RoutedEventArgs e)
        {
            developerTools.Visibility = System.Windows.Visibility.Hidden;
        }


        
    }
}
